package com.aspirecn.auth.web;

import com.aspirecn.auth.common.RestApiResponseHandler;
import com.aspirecn.auth.domain.Menus;
import com.aspirecn.auth.domain.SysAuthority;
import com.aspirecn.auth.domain.SysRole;
import com.aspirecn.auth.domain.SysUser;
import com.aspirecn.auth.domain.vo.*;
import com.aspirecn.auth.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
import org.springframework.web.bind.annotation.*;

import com.aspirecn.auth.infrastructure.OAuth2Constants;
import com.google.code.kaptcha.impl.DefaultKaptcha;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RestController
public class UserController {

    private static final Logger LOG = LoggerFactory.getLogger(UserController.class);
    @Autowired
    @Qualifier("consumerTokenServices")
    ConsumerTokenServices consumerTokenServices;
    @Autowired
    private ISysUserService iSysUserService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private DefaultKaptcha captchaProducer;

    @Value("${kaptcha.expires}")
    private int captchaExpires;

    //查询用户权限
    @GetMapping("/user")
    public Principal user(Principal user) {
        return user;
    }

    //获取验证码图片接口
    @RequestMapping(value = "/captcha", produces = MediaType.IMAGE_JPEG_VALUE)
    public void getRandCode(HttpServletRequest request, HttpServletResponse response) {
        LOG.info("test333333333333333333333333");
        String captchaText = captchaProducer.createText();

        String uuid = UUID.randomUUID().toString();
        String key = OAuth2Constants.CAPTCHA_REDIS_PATH + uuid;
        LOG.info("key={}&captcha={}&expires={}", key, captchaText, captchaExpires);

        redisTemplate.opsForValue().set(key, captchaText, captchaExpires, TimeUnit.SECONDS);
        Cookie cookie = new Cookie(OAuth2Constants.CAPTCHA_COOKIE_KEY, uuid);
        response.addCookie(cookie);

        BufferedImage bi = captchaProducer.createImage(captchaText);
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            ImageIO.write(bi, "jpeg", out);
            out.flush();
        } catch (IOException e) {
            LOG.info("{}", e);
        }
    }

    //退出登陆,注销
    @GetMapping("/token/revoke")
    public ResponseMsg<?> revokeToken(String access_token) {
        LOG.info("test1111111111111111");
        ResponseHead responseHead = new ResponseHead();
        if (consumerTokenServices.revokeToken(access_token)) {
            return RestApiResponseHandler.successResponseMsg(responseHead, "注销成功");
        } else {
            return RestApiResponseHandler.errorResponseMsg(responseHead, "注销失败");
        }
    }

    //修改用户密码
    @PostMapping(value = "/user/updatePwd")
    @ResponseBody
    public ResponseMsg updatePwd(Principal user,
                                 @RequestBody RequestMsg<SysUserPwdUpdateInVo> requestMsg) {

        String newPassword = requestMsg.getData().getNewPassword();
        String oldPassword = requestMsg.getData().getOldPassword();
        ResponseMsg erreoMsg = iSysUserService.updaterUserPwd(newPassword, user.getName(), oldPassword);
        return erreoMsg;
    }

    //动态返回用户菜单
    @GetMapping("/user/menu")
    public ResponseMsg<MenusVo> login(Principal user) {
        ResponseMsg<MenusVo> msg = new ResponseMsg<>();
        ResponseHead head = new ResponseHead();
        // 存放角色id
        List<Long> roleIdList = new ArrayList<>();
        // 集合用来存放用户权限
        ArrayList<SysAuthority> list = new ArrayList<>();
        // 存放一级菜单集合
        List<Menus> menus_first = new ArrayList<>();
        // 存放二级菜单的集合
        List<Menus> menus_second = new ArrayList<Menus>();
        try {
            // 通过用户名查出该用户拥有的所有权限集合
            SysUser sysUser = iSysUserService.findOneByUserName(user.getName());
            if (sysUser != null) {
                Set<SysRole> roles = sysUser.getRoles();
                if (roles != null && roles.size() > 0) {
                    for (SysRole sysRole : roles) {
                        roleIdList.add(sysRole.getId());
                        Set<SysAuthority> authorities = sysRole.getAuthorities();
                        if (authorities != null && authorities.size() > 0) {
                            for (SysAuthority sysAuthority : authorities) {
                                if (!list.contains(sysAuthority)) {
                                    list.add(sysAuthority);
                                }
                            }
                        }
                    }
                }
            }
            menus_first = new ArrayList<Menus>();

            // 2.遍历用户的权限，得到plevel为1 和 2的权限，分别存到一或二级菜单集合
            if (list != null && list.size() > 0) {
                for (SysAuthority sysAuthority : list) {
                    // 获取用户权限
                    String pelevel = sysAuthority.getPelevel();
                    // 一级菜单
                    if ("1".equals(pelevel)) {
                        Menus menus = new Menus();
                        menus.setMenuid(sysAuthority.getParentId());
                        menus.setMenuname(sysAuthority.getName());
                        menus_first.add(menus);
                    }
                    // 二级菜单
                    else if ("2".equals(pelevel)) {
                        Menus menus = new Menus();
                        menus.setMenuid(sysAuthority.getParentId());
                        menus.setMenuname(sysAuthority.getName());
                        menus.setUrl(sysAuthority.getUrl());
                        menus_second.add(menus);
                    }
                }
                // 排序一级目录
                for (int i = 0; i < menus_first.size() - 1; i++) {
                    for (int j = 0; j < menus_first.size() - 1 - i; j++) {
                        Menus m_pre = menus_first.get(j);
                        Menus m_next = menus_first.get(j + 1);
                        if (m_pre.getMenuid().compareTo(m_next.getMenuid()) > 0) {
                            // 将后面的元素加到前面的元素所在的位置
                            menus_first.add(j, m_next);
                            // 再删除原来的后面元素
                            menus_first.remove(j + 2);
                        }
                    }
                }
                // 排序二级目录
                for (int i = 0; i < menus_second.size() - 1; i++) {
                    for (int j = 0; j < menus_second.size() - 1 - i; j++) {
                        Menus m_pre = menus_second.get(j);
                        Menus m_next = menus_second.get(j + 1);
                        if (m_pre.getMenuid().compareTo(m_next.getMenuid()) > 0) {
                            // 将后面的元素加到前面的元素所在的位置
                            menus_second.add(j, m_next);
                            // 再删除原来的后面元素
                            menus_second.remove(j + 2);
                        }
                    }
                }
                for (Menus menu2 : menus_second) {
                    String id = menu2.getMenuid();
                    // 遍历一级菜单集合
                    for (Menus menu1 : menus_first) {
                        // 如果二级菜单的id是以一级菜单id开头的，说明它是该一级菜单的子菜单
                        if (id.startsWith(menu1.getMenuid())) {
                            // 二级菜单加进一级菜单
                            menu1.getMenus().add(menu2);
                        }
                    }
                }
            }
        } catch (Exception e) {
            head.setRequestId("1");
            head.setRespCode("01");
            head.setRespStatus("01");
            head.setRespDesc("返回菜单失败!");
            msg.setHead(head);
            msg.setData(new MenusVo());
            return msg;
        }
        head.setRequestId("1");
        head.setRespCode("00");
        head.setRespStatus("00");
        head.setRespDesc("返回菜单成功!");
        MenusVo menusVo = new MenusVo();
        menusVo.setMenu(menus_first);
        menusVo.setRoleid(roleIdList.get(0) + "");
        menusVo.setUsername(user.getName());
        msg.setData(menusVo);
        msg.setHead(head);
        return msg;
    }
}
